package com.bestvike.stone.core.threading;

import com.bestvike.stone.core.reflect.ReflectionUtils;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * Created by 许崇雷 on 2017/5/26.
 */
public final class ThreadUtils {
    private static final Field FIELD_THREAD_LOCALS = Objects.requireNonNull(ReflectionUtils.getField(Thread.class, "threadLocals", false));
    private static final Field FIELD_INHERITABLE_THREAD_LOCALS = Objects.requireNonNull(ReflectionUtils.getField(Thread.class, "inheritableThreadLocals", false));
    private static final Method METHOD_CREATE_INHERITED_MAP = Objects.requireNonNull(ReflectionUtils.getMethod(ThreadLocal.class, "createInheritedMap", new Class[]{FIELD_INHERITABLE_THREAD_LOCALS.getType()}, true));

    /**
     * 休眠制定的毫秒数,如果失败直接返回
     *
     * @param millis 休眠毫秒数
     */
    public static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (Exception ignored) {
        }
    }

    /**
     * 获取线程的 threadLocals 字段值
     */
    public static Object getThreadLocals(Thread thread) {
        Assert.notNull(thread, "thread can not be null");
        try {
            return FIELD_THREAD_LOCALS.get(thread);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置线程的 threadLocals 字段值
     */
    public static void setThreadLocals(Thread thread, Object threadLocals) {
        Assert.notNull(thread, "thread can not be null");
        try {
            FIELD_THREAD_LOCALS.set(thread, threadLocals);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取线程的 inheritableThreadLocals 字段值
     */
    public static Object getInheritableThreadLocals(Thread thread) {
        Assert.notNull(thread, "thread can not be null");
        try {
            return FIELD_INHERITABLE_THREAD_LOCALS.get(thread);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置线程的 inheritableThreadLocals 字段值
     */
    public static void setInheritableThreadLocals(Thread thread, Object inheritableThreadLocals) {
        Assert.notNull(thread, "thread can not be null");
        try {
            FIELD_INHERITABLE_THREAD_LOCALS.set(thread, inheritableThreadLocals);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 复制线程的 inheritableThreadLocals 字段值
     */
    public static Object copyInheritableThreadLocals(Thread thread) {
        Assert.notNull(thread, "thread can not be null");
        Object inheritableThreadLocals = getInheritableThreadLocals(thread);
        try {
            return inheritableThreadLocals == null ? null : METHOD_CREATE_INHERITED_MAP.invoke(null, inheritableThreadLocals);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
